#include "stm32f1xx_hal.h"
#include "logic_implementation.h"
#include "HAL_OLED.h"
#include <stdio.h>
#include "tim.h"
#include "encoder.h"
#include "key_nodelay.h"
#include "string.h"
#include "usart.h"
#include "dma.h"
#include "bubble_sort.h"
#include "DAC8552.h"

Key_Handler hkey1;//切换模式
uint8_t flag_1st = 0;

float FeedBack = 0;//反馈增益

uint16_t circle = 0;

uint8_t cnt;

uint8_t Flag_Stop = 0;


void Driever_Init(void)
{
	//初始化DAC8552模块
	DAC8552_Init();
	
	//初始化OLED模块
	OLED_Init();
	
	//初始化编码器模块
	Encoder_Init();
	
	Key_Init();
	hkey1.flag = 1;
	hkey1.Key_cnt = 0;
	hkey1.GPIO_PIN = GPIO_PIN_1;
	
	
	ON_OFF_Init();
	
	flag_1st = 1;
	
	//初始化pid参数
	hpidV.Kp = 0.08;
	hpidV.Ki = 0.02;
	hpidV.Kd = 0.06;
	hpidV.PreError = 0;
	hpidV.Sum_E = 0;
	
	hpidA.Kp = 0.4;
	hpidA.Ki = 0.1;
	hpidA.Kd = 0.3;
	hpidA.PreError = 0;
	hpidA.Sum_E = 0;
	
}

void Data_Struct_Init(Data_TypedefStruct* hdata)
{
	hdata->Ic = 0;
	hdata->Iset = 0;
	hdata->Uc = 0;
	hdata->state = 0;
	hdata->Uc = 0;
	hdata->Ui = 0;
	hdata->Uset = 0;
	hdata->Uout = 0;
	hdata->Voltage_Ture = 0;
	
	
}

/**
  * @brief 检测电压电流，并完成转换
  *        	//data[0] -> Ui
						//data[1] -> Uc   
						//data[2] -> Vref
  * @param 				
  * 
  * @retval 
  */


//float arr_v[CIRCLE] ={0};
//float arr_i[CIRCLE] ={0};
uint8_t PreState = 0;

void VI_Detect(uint32_t* data, Data_TypedefStruct* hdata)
{
	hdata->Voltage_Ture = 4095.0f *1.2f/(uint16_t)data[2];
	
	//arr_v[circle] = (uint16_t)data[1]/4095.0f *Vref;  //
	hdata->Uc= (uint16_t)data[1]/4095.0f *Vref;  //
	hdata->Ui = (uint16_t)data[0]/4095.0f *Vref;
	
	hdata->Ic= (hdata->Ui/15.0f)/Rc*1000.0f;
	
	hdata->Uout = 6*hdata->Uc - hdata->Ui/15.0f- CLRT_VALUE;
	
	//输出电压校准
//	if(hdata->Uout <= 1.0f)
//	{
//		hdata->Uout = 0.16f;
//		
//	}
	if(hdata->Uout <= 2.0f)
	{
		hdata->Uout += 0.25f;
		
	}
//	else if(hdata->Uout <= 5.5f)	
//	{
//		hdata->Uout -= 0.1f;

//	}	
//	else if(hdata->Uout <= 6.2)	
//	{
//		hdata->Uout -= 0.1f;

//	}		
//	else if(hdata->Uout >= 8)	
//	{
//		hdata->Uout -= 0.2f;

//	}		
	
	//输出电流校准
	if(hdata->Ic <= 0.25f)
	{
		hdata->Ic -= 0.025f;
		
	}
	else if(hdata->Ic <= 0.45f)	
	{
		hdata->Ic -= 0.05f;

	}	
	else if(hdata->Ic <= 1.0f)	
	{
		hdata->Ic -= 0.125f;

	}	
	
	else if(hdata->Ic <= 1.8f)	
	{
		hdata->Ic -= 0.2f;

	}		
	else
	{
		hdata->Ic -= 0.25f;
	}
	
	
	
	//过流保护后恢复
	if(hdata->Ic >= I_MAX)
	{
		ON_OFF_SET(OFF);
		PreState = hdata->state;
		
		Set_const_V(0, 0);
		hpidA.Sum_E = 0;
		hpidV.Sum_E = 0;
		
		if(PreState == 1)
		{
			hdata->Uset = 0.5;
		}
		else if(PreState == 2)
		{
			hdata->Uset = 0.5;
		}
		hdata->state = 0;
		OLED_Clear();
		Flag_Stop = 1;
	}
	if(hdata->Ic < (I_MAX - 0.5)&& Flag_Stop == 1)
	{
		hpidA.Sum_E = 0;
		hpidV.Sum_E = 0;
		
		OLED_Clear();
		Flag_Stop = 0;
		hdata->state = PreState;
		if(PreState == 1)
		{
			cnt = hdata->Uset/0.1;
			Set_const_V(hdata->Uset, 0);
			HAL_Delay(20);
		}
		else if(PreState == 2)
		{
			Set_const_V(hdata->Uset, 0);
			HAL_Delay(20);
		}
		 
		PreState = 0;
		
	}
	
}

void Get_VI(Data_TypedefStruct* hdata, float* arr_v, float* arr_i)
{
	Bubble_Sort(arr_v,CIRCLE);
	Bubble_Sort(arr_i, CIRCLE);
	
	float V_Sum = 0;
	float I_Sum = 0;
	
	for(uint8_t i = 10;i < CIRCLE-10; i++)
	{
		V_Sum += arr_v[i];
		I_Sum += arr_i[i];
		
	}
	
	hdata->Uc = 1.0f*V_Sum/(CIRCLE-20);
	hdata->Ic = 1.0f*I_Sum/(CIRCLE-20);
	
	
}


//按键和编码器的逻辑实现输入参数
uint8_t cnt = 0;
uint8_t precnt = 0;
uint8_t Key1_flag = 0;
void Input_Value(Data_TypedefStruct* hdata)
{
	
	precnt = cnt;
	cnt = Encoder_GetCounter();
	
	//要解决从0反转到100的问题 && LockFlag == 0
	if(cnt - precnt > 1)
	{
		Encoder_SetCounter(precnt);
		cnt = precnt;
		
	}
	if(precnt - cnt> 1)
	{
		Encoder_SetCounter(precnt);
		cnt = precnt;
	}
	
	Key1_flag = KeyScan(&hkey1);
	
	//按键一，状态切换
	if(Key1_flag)
	{
		flag_1st = 1;
		FeedBack = 0.0;
		hpidV.Sum_E = 0;
		hpidA.Sum_E = 0;
		
		Set_const_V(0,0);
		HAL_Delay(100);
		
		hdata->state++;	
		hdata->state %= 3;
	}
	
	//恒压源设置电压
	if(hdata->state == 1)
	{
		ON_OFF_SET(ON);
		if(flag_1st == 1)
		{
			FeedBack = 0;
			cnt = 0;
			flag_1st = 0;
			Encoder_SetARR(100);
		}
		hdata->Uset = cnt/10.0f;
		
	}
	
	else if(hdata->state == 2)
	{
		if(flag_1st == 1)
		{
			FeedBack = 0.0;
			cnt = 0;
			Encoder_SetARR(40);
			flag_1st = 0;
			
		}
		hdata->Iset = cnt*0.05f;
	}
	else if(hdata->state == 0)
	{
		if(flag_1st == 1)
		{
			cnt = 0;
			flag_1st = 0;
			ON_OFF_SET(OFF);
				
		}
	}
}



void SetValue(Data_TypedefStruct* hdata)
{
	
	//电压环
	if(hdata->state ==1)
	{
		float U_in =0;
		
			FeedBack = PID(hdata->Uout, hdata->Uset, &hpidV);
			U_in = FeedBack + hdata->Uout/4.0f;
			
			Set_const_V(U_in, FeedBack);
	}
	
	//电流环
	else if(hdata->state ==2)
	{
		
		float Us = 0;
		
		FeedBack = PID(hdata->Ic, hdata->Iset, &hpidA);
		Us = FeedBack + hdata->Uout/4.0f;
		
		Set_const_I(Us, FeedBack);
	}
	
}


void Set_const_V(float Value, float fb)
{
	DAC8552_WriteB(Value, fb);
}

void Set_const_I(float Value, float fb)
{
	DAC8552_WriteB(Value,fb);
}


//OLED显示
void OLED_SHOW(Data_TypedefStruct* hdata)
{
	char c_data[7][20];
	
	sprintf(c_data[0], "%0.2f", DAC8552_GetValueForChannelB());
	sprintf(c_data[1], "%0.2f", hdata->Uout);
	sprintf(c_data[2], "%0.2f", hdata->Ic);
	sprintf(c_data[3], "%0.2f", FeedBack);
	sprintf(c_data[4], "%0.1f", hdata->Uset);
	sprintf(c_data[5], "%0.2f", hdata->Iset);
	sprintf(c_data[6], "%0.2f", hpidV.Sum_E);
	
	
	//显示输出电压
	OLED_ShowString(1,1,"Uout:");
	OLED_ShowString(1,7 ,c_data[1]);
	
	//显示输出的电流
	OLED_ShowString(2,1,"Iout:");
	OLED_ShowString(2,4,c_data[2]);
	
	//显示状态
	if(hdata->state == 1)
	{
		OLED_ShowString(3,1,"Vset:");
		OLED_ShowString(3,7,c_data[4]);
		OLED_ShowString(4,13,"-V-");
	}
	else if(hdata->state == 2)
	{
		OLED_ShowString(3,1,"Iset:");
		OLED_ShowString(3,7,c_data[5]);
		OLED_ShowString(4,13,"-A-");
	}
	else if(hdata->state == 0)
	{
		OLED_ShowString(3,1,"            ");
		OLED_ShowString(4,13,"OFF");
		if(Flag_Stop==1)
		{
			OLED_Clear();
			OLED_ShowString(2,4,"!!!ERROR!!!");
			HAL_Delay(1500);
		}
	}
	
	//反馈
	OLED_ShowString(4,1, c_data[3]);
	OLED_ShowString(4,7, c_data[0]);
	
	//显示积分增益
	OLED_ShowString(2,9,c_data[6]);
	
	
//	//从串口发送数据
//	if(hdata->state != 0)
//	{
//		USART_Send(hdata);
//	}
	
}


//串口发送数据到电脑
//void USART_Send(Data_TypedefStruct* hdata)
//{
//	char data[50];
//	
//	sprintf(data, "%0.2f,%0.2f,%0.3f,%0.2f,%0.2f,%0.3f\n", (4*hdata->Uc), hdata->Ic, FeedBack, hdata->Uset,hdata->Iset,hdata->Iset-hdata->Ic);
//	
//	
//	HAL_UART_Transmit(&huart2, (uint8_t *)data, strlen(data),5);
//	
//	
//}


void ON_OFF_Init(void)
{
	__HAL_RCC_GPIOC_CLK_ENABLE();
	
	GPIO_InitTypeDef GPIO_InitStruct = {0}; 

	GPIO_InitStruct.Pin = GPIO_PIN_13;
	GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
	GPIO_InitStruct.Pull = GPIO_NOPULL;
	GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
	HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
	
}

void ON_OFF_SET(LM2596_State State)
{
	HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13,  (GPIO_PinState)State);
}


















